#include <iostream>
// #include <unistd.h>
// #include <cstdio>
// #include <cstring>
// #include <sys/types.h>
// #include <sys/wait.h>

// int main()
// {
//     int pipefd[2];
//     pipe(pipefd);

//     pid_t pid = fork();
//     if (pid == 0)
//     {
//         // child process
//         close(pipefd[0]);
//         std::string str = "hello, world";
//         write(pipefd[1], str.c_str(), str.size() + 1);
//         close(pipefd[1]);
//         exit(0);
//     }
//     else
//     {
//         // parent process
//         close(pipefd[1]);
//         char buffer[1024];
//         read(pipefd[0], buffer, 1024);
//         std::cout << "read from child: " << buffer << std::endl;
//         close(pipefd[0]);
//         wait(NULL);
//     }

//     return 0;
// }

// #include <iostream>
// #include <unistd.h>
// #include <cstring>
// #include <sys/types.h>
// #include <sys/wait.h>
// #include <vector>

// void ChildWrite(int wfd, int child_id)
// {
//     char buffer[1024];
//     int cnt = 0;
//     while (cnt < 5) // 每个子进程只写入5次
//     {
//         snprintf(buffer, sizeof(buffer), "I am child, pid: %d, id: %d, cnt: %d", getpid(), child_id, cnt++);
//         write(wfd, buffer, strlen(buffer));
//         sleep(1);
//     }
//     // 发送结束消息
//     const char *endMessage = "end";
//     write(wfd, endMessage, strlen(endMessage));
//     close(wfd);
//     exit(0);
// }

// void FatherRead(int rfd)
// {
//     char buffer[1024];
//     while (true)
//     {
//         buffer[0] = 0;
//         ssize_t n = read(rfd, buffer, sizeof(buffer) - 1);
//         if (n > 0)
//         {
//             buffer[n] = 0;
//             if (strcmp(buffer, "end") == 0) // 检查结束消息
//             {
//                 std::cout << "Received end message from child" << std::endl;
//                 continue; // 继续读取，直到所有子进程结束
//             }
//             std::cout << "child say: " << buffer << std::endl;
//         }
//     }
//     close(rfd);
// }

// int main()
// {
//     // 1. 创建管道
//     int fds[2] = {0}; // fds[0]:读端   fds[1]: 写端
//     int n = pipe(fds);
//     if (n < 0)
//     {
//         std::cerr << "pipe error" << std::endl;
//         return 1;
//     }
//     std::cout << "fds[0]: " << fds[0] << std::endl;
//     std::cout << "fds[1]: " << fds[1] << std::endl;

//     // 2. 创建子进程池
//     int num_children = 3; // 子进程数量
//     std::vector<pid_t> children(num_children);
//     for (int i = 0; i < num_children; ++i)
//     {
//         pid_t id = fork();
//         if (id == 0)
//         {
//             // child process
//             close(fds[0]);
//             ChildWrite(fds[1], i);
//         }
//         else if (id > 0)
//         {
//             children[i] = id;
//         }
//         else
//         {
//             std::cerr << "fork error" << std::endl;
//             close(fds[0]);
//             close(fds[1]);
//             return 1;
//         }
//     }

//     // 3. 关闭不需要的写端
//     close(fds[1]);

//     // 4. 父进程读取数据
//     FatherRead(fds[0]);

//     // 5. 父进程等待所有子进程结束
//     for (int i = 0; i < num_children; ++i)
//     {
//         waitpid(children[i], nullptr, 0);
//     }

//     // 6. 关闭读端
//     close(fds[0]);

//     return 0;
// }

#include <iostream>
#include <unistd.h>
#include <cstring>
#include <sys/types.h>
#include <sys/wait.h>
#include <vector>

void ChildWrite(int wfd, int child_id)
{
    char buffer[1024];
    int cnt = 0;
    while (cnt < 5)
    {
        snprintf(buffer, sizeof(buffer), "I am child, pid: %d, id: %d, cnt: %d\n", getpid(), child_id, cnt++);
        write(wfd, buffer, strlen(buffer));
        sleep(1);
    }
    snprintf(buffer, sizeof(buffer), "end:%d\n", child_id); // 包含子进程ID的结束标记
    write(wfd, buffer, strlen(buffer));
    close(wfd);
    exit(0);
}

void FatherRead(int rfd, int num_children)
{
    char buffer[1024];
    std::string remaining;
    int ended_children = 0;

    while (true)
    {
        ssize_t n = read(rfd, buffer, sizeof(buffer) - 1);
        if (n > 0)
        {
            buffer[n] = 0;
            remaining.append(buffer);

            size_t pos;
            while ((pos = remaining.find('\n')) != std::string::npos)
            {
                std::string message = remaining.substr(0, pos);
                remaining.erase(0, pos + 1);

                if (message.find("end:") == 0)
                {
                    int child_id = std::stoi(message.substr(4));
                    std::cout << "Child " << child_id << " ended.\n";
                    if (++ended_children >= num_children)
                    {
                        std::cout << "All children ended.\n";
                        close(rfd);
                        return;
                    }
                }
                else
                {
                    std::cout << "child say: " << message << std::endl;
                }
            }
        }
        else if (n == 0)
        {
            std::cout << "All write ends closed.\n";
            break;
        }
        else
        {
            perror("read");
            break;
        }
    }
    close(rfd);
}

int main()
{
    int fds[2];
    if (pipe(fds))
    {
        std::cerr << "pipe error" << std::endl;
        return 1;
    }

    const int num_children = 3;
    std::vector<pid_t> children(num_children);

    for (int i = 0; i < num_children; ++i) {
        if (pid_t id = fork(); id == 0)
        {
            close(fds[0]);
            ChildWrite(fds[1], i);
        }
        else if (id > 0)
        {
            children[i] = id;
        }
        else
        {
            std::cerr << "fork error\n";
            close(fds[0]);
            close(fds[1]);
            return 1;
        }
    }

    close(fds[1]);
    FatherRead(fds[0], num_children);

    for (int i = 0; i < num_children; ++i) {
        waitpid(children[i], nullptr, 0);
    }

    close(fds[0]);
    return 0;
}